import os
import time
import sys
import requests
import netifaces
from setting import logger, NS_HOST
from ns import Ns

import threading
import ipaddress
from concurrent.futures import ThreadPoolExecutor
from queue import Queue

class FindMaster:

    def __init__(self) -> None:
        
        self.network_info = self.get_network_info()

        self.queue = Queue()

        


    @staticmethod
    def get_network_info(interface="eth0"):
        """\
        >>> get_network_info("eth0")
        >>> {'ip_address': '192.168.88.200', 'netmask': '255.255.255.0', 'gateway': '192.168.88.1'}
        """
        info = {}
        addrs = netifaces.ifaddresses(interface)
        
        if netifaces.AF_INET in addrs:
            info['ip_address'] = addrs[netifaces.AF_INET][0]['addr']
            info['netmask'] = addrs[netifaces.AF_INET][0]['netmask']
            info['gateway'] = netifaces.gateways()[netifaces.AF_INET][0][0]
            # info['broadcast'] = addrs[netifaces.AF_INET][0]['broadcast']
            with open("/root/.self_host", "w") as f:

                f.write(info['ip_address'])
        else:
            
            return None
        
        return info
    
    @staticmethod
    def subnet_mask_to_cidr(subnet_mask):
        binary_mask = ''.join(format(int(octet), '08b') for octet in subnet_mask.split('.'))
        cidr = sum(int(bit) for bit in binary_mask)
        return str(cidr)
        
    @staticmethod
    def check_ip_is_master_station(ip = "192.168.31.121"):
        '''检查ip是否是主站'''

        host = f"http://{ip}:8080/is_master_station"

        # host= "http://192.168.31.121:8080/is_master_station"

        try:
            r = requests.get(url = host, timeout=0.1)
        
        except Exception as e:

            logger.error(f"{ip}: 不是主站")

            logger.error(str(e))

            return False

        else:

            print(r.text)

            if r.text.strip() == "true":

                return True
            
            else:

                return False
            
    def worker(self):
        while not self.queue.empty():

            ip = self.queue.get()

            if self.check_ip_is_master_station(ip):

                with open("/root/.master_host", "w") as f:

                    f.write(ip)
                    f.flush()

                logger.info("_"*20)

                logger.info(f"------主站IP找到： {ip}------")

                logger.info("_"*20)

                self.queue.queue.clear()
                # sys.exit()
    
                # 或者在这里进行其他操作，比如保存到文件等
        
    def find_master_station_ips(self, base_ip, netmask):

        star_time = time.time()
    
        network = ipaddress.ip_network(f"{base_ip}/{netmask}", strict=False)
        for ip in network.hosts():
            self.queue.put(str(ip))

        threads = []
        thread_count = 10  # 设置线程数
        for _ in range(thread_count):
            t = threading.Thread(target=self.worker)
            t.start()
            threads.append(t)

        for t in threads:
            t.join()

        logger.info(f"查找主站耗时：{time.time() - star_time}")

    def find_master(self, netmask="24"): 

        if not self.network_info:

            return None
        
        ip_address = self.network_info["ip_address"]

        # netmask = self.subnet_mask_to_cidr(self.get_network_info["netmask"])

        self.find_master_station_ips(ip_address, netmask)

        try:
            with open("/root/.master_host") as f:

                    master_ip =  f.read()
            
        except Exception as e:

            return None
        
        else:

            logger.info(f"主站Ip: {master_ip}")

            return master_ip
            

    # def find_master(self): # 单线程查找master

    #     if not self.network_info:

    #         return None
        
    #     ip_address = self.network_info["ip_address"]

    #     ip_list = ip_address.split('.')

    #     for i in range(2, 255):

    #         ip_list[-1] = str(i)

    #         check_ip = ".".join(ip_list)

    #         if self.check_ip_is_master_station(check_ip):

    #             return check_ip
            
    #     else:

    #         return None
        
        
    def sentry_master(self):

        if not os.path.isfile("/root/.master_host"):

            master_host = self.find_master() # 先查子网掩码默认值24

            if master_host == None and self.network_info["netmask"] != "255.255.255.0": # 如果没有找到且子网掩码不是 24

                master_host = self.find_master(self.subnet_mask_to_cidr(self.get_network_info["netmask"]))

            if master_host:

                Ns(NS_HOST).set_connector_mqtt_host(master_host) # 重置NS connerctor

                return
            else:

                logger.error("主站未找到")

                return
            
            
        with open("/root/.master_host") as f:

            master_host = f.read()

        if not self.check_ip_is_master_station(master_host):

            os.remove("/root/.master_host")

            return
        
        # 最后排查一下ns connector_info 是否有错误
        ns = Ns(NS_HOST)

        connector_info = ns.get_connector_info()

        now_uri = connector_info["uri"]

        true_uri = f'mqtt://{master_host}:1883'

        if connector_info["failed"] != [] or now_uri != true_uri:

            ns.set_connector_mqtt_host(master_host)

        


if __name__ == "__main__":


    while True:

        f = FindMaster()

        try:

            f.sentry_master()

        except Exception as e:

            logger.error(str(e))
            raise

        else:

            time.sleep(60*3)

            
